package com.tengits.tcos;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.net.MalformedURLException;

import com.facebook.react.bridge.Promise;

import com.tencent.cos.xml.CosXmlServiceConfig;
import com.tencent.cos.xml.CosXmlSimpleService;
import com.tencent.cos.xml.exception.CosXmlClientException;
import com.tencent.cos.xml.exception.CosXmlServiceException;
import com.tencent.cos.xml.listener.CosXmlResultListener;
import com.tencent.cos.xml.model.CosXmlRequest;
import com.tencent.cos.xml.model.CosXmlResult;
import com.tencent.cos.xml.transfer.COSXMLUploadTask;
import com.tencent.cos.xml.transfer.TransferConfig;
import com.tencent.cos.xml.transfer.TransferManager;
import com.tencent.qcloud.core.auth.QCloudCredentialProvider;
import com.tencent.qcloud.core.auth.SessionCredentialProvider;
import com.tencent.qcloud.core.http.HttpRequest;
import com.tencent.qcloud.core.http.RequestBodySerializer;

import org.json.JSONObject;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import android.text.TextUtils;
import android.util.Log;
import java.io.File;

public class TencentCosModule extends ReactContextBaseJavaModule {

    private static final String TAG = TencentCosModule.class.getSimpleName();

    private final ReactApplicationContext reactContext;
    private TransferManager mTransferManager;
    private String mAppID;
    private String mBucket;
    private int mSystemId;

    public TencentCosModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "TencentCos";
    }

    @ReactMethod
    public void initCosService(String appid, String bucket, String region, String cookie, String signUrl, int systemId, final Promise promise) {
        
        Log.e(TAG, "initCosServer"+signUrl);
        mAppID = appid;
        mBucket = bucket;
        mSystemId = systemId;

        CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder()
                .isHttps(false)
                .setRegion(region)
                .setDebuggable(true)
                .builder();

        URL url = null;

        try {
            url = new URL(signUrl);
        } catch (MalformedURLException e) {
            promise.resolve(e.getMessage());
        }

        /**
         * 初始化 {@link QCloudCredentialProvider} 对象，来给 SDK 提供临时密钥。
         */
        Map<String,String> entity = new HashMap<>();
        entity.put("bucket",mBucket+"-"+mAppID);
        entity.put("region",region);
        if(systemId > 0)
        {
            entity.put("systemId", ""+systemId);
        }
        JSONObject json =new JSONObject(entity);
        HttpRequest.Builder<String> build = new HttpRequest.Builder<String>();
        build.url(url).method("POST").body(RequestBodySerializer.string("application/json; charset=utf-8",json.toString()));
        if(!TextUtils.isEmpty(cookie)) {
            build.addHeader("authorization",cookie);
        }
        QCloudCredentialProvider credentialProvider = new SessionCredentialProvider(build.build());

        CosXmlSimpleService cosXmlService = new CosXmlSimpleService(this.reactContext, cosXmlServiceConfig, credentialProvider);

        TransferConfig transferConfig = new TransferConfig.Builder()
                .setDividsionForCopy(5 * 1024 * 1024) // 是否启用分块复制的最小对象大小
                .setSliceSizeForCopy(5 * 1024 * 1024) // 分块复制时的分块大小
                .setDivisionForUpload(2 * 1024 * 1024) // 是否启用分块上传的最小对象大小
                .setSliceSizeForUpload(1024 * 1024) // 分块上传时的分块大小
                .build();
    
        mTransferManager = new TransferManager(cosXmlService, transferConfig);

        promise.resolve("success");
    }

    @ReactMethod
    public void upload(String originLocalPath, String targetPath, final Promise promise) {

        if(mTransferManager == null) {
            promise.resolve(-1);
            return;
        }

        String cosPath = targetPath + String.valueOf(System.currentTimeMillis()/1000) + new File(originLocalPath).getName();

        String localPath = originLocalPath.replace("file://", "");

        Log.e("cos", "target:" + cosPath + "|local:" + localPath);

        // 开始上传，并返回生成的 COSXMLUploadTask
        COSXMLUploadTask cosxmlUploadTask = mTransferManager.upload(mBucket+"-"+mAppID, cosPath,
                localPath, null);

        // 设置结果监听
        cosxmlUploadTask.setCosXmlResultListener(new CosXmlResultListener() {
        @Override
        public void onSuccess(final CosXmlRequest request, final CosXmlResult ret) {
            Log.e("cos", "success" + ret.accessUrl);
            // Call the desired channel message here.
            promise.resolve(ret.accessUrl);
        }

        @Override
        public void onFail(final CosXmlRequest request, final CosXmlClientException exception, final CosXmlServiceException serviceException) {
            // todo Upload failed because of CosXmlClientException or CosXmlServiceException...
            Log.e("cos", "exception");
                // Call the desired channel message here.
            promise.reject(serviceException != null?serviceException.getLocalizedMessage():
                    exception != null ? exception.getLocalizedMessage():request.getRequestURL());
        }
        });
  }

      @ReactMethod
    public void uploadWithName(String originLocalPath, String targetPath, final Promise promise) {

        if(mTransferManager == null) {
            promise.resolve(-1);
            return;
        }

        String cosPath = targetPath;

        String localPath = originLocalPath.replace("file://", "");

        Log.e("cos", "target:" + cosPath + "|local:" + localPath);

        // 开始上传，并返回生成的 COSXMLUploadTask
        COSXMLUploadTask cosxmlUploadTask = mTransferManager.upload(mBucket+"-"+mAppID, cosPath,
                localPath, null);

        // 设置结果监听
        cosxmlUploadTask.setCosXmlResultListener(new CosXmlResultListener() {
        @Override
        public void onSuccess(final CosXmlRequest request, final CosXmlResult ret) {
            Log.e("cos", "success" + ret.accessUrl);
            // Call the desired channel message here.
            promise.resolve(ret.accessUrl);
        }

        @Override
        public void onFail(final CosXmlRequest request, final CosXmlClientException exception, final CosXmlServiceException serviceException) {
            // todo Upload failed because of CosXmlClientException or CosXmlServiceException...
            Log.e("cos", "exception");
                // Call the desired channel message here.
            promise.reject(serviceException != null?serviceException.getLocalizedMessage():
                    exception != null ? exception.getLocalizedMessage():request.getRequestURL());
        }
        });
  }
}
